package com.iflytek.voicecloud.rtasr.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.iflytek.voicecloud.rtasr.DraftWithOrigin;
import com.iflytek.voicecloud.rtasr.util.EncryptUtil;
import org.java_websocket.WebSocket;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.drafts.Draft;
import org.java_websocket.handshake.ServerHandshake;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLEncoder;
import java.nio.ByteBuffer;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;

/**
 * 实时转写服务类
 */
public class RTASRService {

    // appid
    private static final String APPID = "b4ae6555";

    // appid对应的secret_key
    private static final String SECRET_KEY = "d9094b5522c962ba2da277bf28a45b58";

    // 请求地址
    private static final String HOST = "rtasr.xfyun.cn/v1/ws";

    private static final String BASE_URL = "wss://" + HOST;

    private static final String ORIGIN = "https://" + HOST;

    // 每次发送的数据大小 1280 字节
    private static final int CHUNCKED_SIZE = 1280;

    // 日期格式化工具
    private static final SimpleDateFormat sdf = new SimpleDateFormat("yyy-MM-dd HH:mm:ss.SSS");

    // 新增多会话句子列表存储
    private static final ConcurrentHashMap<String, List<SentenceInfo>> sentenceStore = new ConcurrentHashMap<>();
    private static final ConcurrentHashMap<String, List<String>> enhancedResultsStore = new ConcurrentHashMap<>();

    // 9. 新增WebSocket客户端存储映射
    private final ConcurrentHashMap<String, MyWebSocketClient> clientStore = new ConcurrentHashMap<>();

    /**
     * 获取指定会话的最新增强识别结果（即最后一项）
     *
     * @param sessionId 会话ID
     * @return 最新的增强识别结果，若无结果则返回 null
     */
    public static String getLastEnhancedResult(String sessionId) {
        List<String> enhancedResults = enhancedResultsStore.get(sessionId);
        if (enhancedResults != null && !enhancedResults.isEmpty()) {
            return enhancedResults.get(enhancedResults.size() - 1);
        }
        return null;
    }

    //获取增强处理结果
    public static List<String> getEnhancedResults(String sessionId) {
        return enhancedResultsStore.get(sessionId);
    }

    // 10. 新增创建WebSocket客户端方法
    public MyWebSocketClient createWebSocketClient(String sessionId, WebSocketSession frontSession) throws Exception {
        URI url = new URI(BASE_URL + getHandShakeParams(APPID, SECRET_KEY));
        DraftWithOrigin draft = new DraftWithOrigin(ORIGIN);
        CountDownLatch handshakeSuccess = new CountDownLatch(1);
        CountDownLatch connectClose = new CountDownLatch(1);

        MyWebSocketClient client = new MyWebSocketClient(url, draft, handshakeSuccess, connectClose, frontSession); // 传递 session

        // 11. 连接并保持客户端存活
        client.connect();
        storeClient(sessionId, client);

        // 等待连接关闭时清理
        new Thread(() -> {
            try {
                connectClose.await();
                removeClient(sessionId);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();

        return client;
    }

    // 客户端存储方法
    private void storeClient(String sessionId, MyWebSocketClient client) {
        clientStore.put(sessionId, client);
    }

    private void removeClient(String sessionId) {
        clientStore.remove(sessionId);
    }

    /**
     * 处理音频字节数组并返回转写结果
     *
     * @param audioBytes 音频字节数组
     * @return 转写结果
     */
    public String processAudioStream(byte[] audioBytes) throws Exception {
        return "已启用实时转发模式";
    }

    // 生成握手参数
    public static String getHandShakeParams(String appId, String secretKey) {
        String ts = System.currentTimeMillis() / 1000 + "";
        String signa = "";
        try {
            signa = EncryptUtil.HmacSHA1Encrypt(EncryptUtil.MD5(appId + ts), secretKey);
            return "?appid=" + appId + "&ts=" + ts + "&signa=" + URLEncoder.encode(signa, "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        }

        return "";
    }

    // 发送数据到WebSocket客户端
    public static void send(WebSocketClient client, byte[] bytes) {
        if (client.isClosed()) {
            throw new RuntimeException("client connect closed!");
        }

        // 等待连接就绪
        while (!client.getReadyState().equals(WebSocket.READYSTATE.OPEN)) {
            try {
                Thread.sleep(100); // 等待连接就绪
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                throw new RuntimeException("连接建立中断", e);
            }
        }

        client.send(bytes);
    }

    // 获取当前时间字符串
    public static String getCurrentTimeStr() {
        return sdf.format(new Date());
    }

    // 自定义WebSocket客户端
    public static class MyWebSocketClient extends WebSocketClient {

        private CountDownLatch handshakeSuccess;
        private CountDownLatch connectClose;
        private final WebSocketSession frontSession; // 新增字段

        public MyWebSocketClient(URI serverUri, Draft protocolDraft, CountDownLatch handshakeSuccess, CountDownLatch connectClose, WebSocketSession frontSession) {
            super(serverUri, protocolDraft);
            this.handshakeSuccess = handshakeSuccess;
            this.connectClose = connectClose;
            this.frontSession = frontSession;
            if (serverUri.toString().contains("wss")) {
                trustAllHosts(this);
            }
        }

        @Override
        public void onOpen(ServerHandshake handshake) {
            System.out.println(getCurrentTimeStr() + "\t讯飞连接建立成功！");
        }

        @Override
        public void onMessage(String msg) {
            String sessionId = frontSession.getId();
            JSONObject msgObj = JSON.parseObject(msg);
//            System.out.println(getCurrentTimeStr() + "\t收到讯飞消息：" + msg);
            String action = msgObj.getString("action");
            if ("result".equals(action)) {
                String data = msgObj.getString("data");
                String enhanced = RTASRService.getContent(data, frontSession); // 传递 frontSession
                // 新增判断：如果增强结果是"doing"则不存储
                if (!"doing".equals(enhanced)) {
                    enhancedResultsStore.computeIfAbsent(sessionId, k -> new ArrayList<>())
                            .add(enhanced);
                }
                try {
                    // 使用前端的 WebSocketSession 发送消息
                    if (frontSession.isOpen()) {
                        frontSession.sendMessage(new TextMessage(enhanced));
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        @Override
        public void onError(Exception e) {
            System.out.println(getCurrentTimeStr() + "\t连接发生错误：" + e.getMessage() + ", " + new Date());
            e.printStackTrace();
            System.exit(0);
        }

        @Override
        public void onClose(int arg0, String arg1, boolean arg2) {
            System.out.println(getCurrentTimeStr() + "\t讯飞星火链接关闭");
            connectClose.countDown();

            // 清理会话数据
            if (frontSession != null && frontSession.isOpen()) {
                String sessionId = frontSession.getId();
                RTASRService.sentenceStore.remove(sessionId);
                RTASRService.enhancedResultsStore.remove(sessionId); // 清理增强结果
            }
        }

        @Override
        public void onMessage(ByteBuffer bytes) {
            try {
                System.out.println(getCurrentTimeStr() + "\t服务端返回：" + new String(bytes.array(), "UTF-8"));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }

        // 信任所有主机
        public void trustAllHosts(MyWebSocketClient appClient) {
            System.out.println("wss");
            TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
                @Override
                public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                    return new java.security.cert.X509Certificate[]{};
                }

                @Override
                public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
                }

                @Override
                public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
                }
            }};

            try {
                SSLContext sc = SSLContext.getInstance("TLS");
                sc.init(null, trustAllCerts, new java.security.SecureRandom());
                appClient.setSocket(sc.getSocketFactory().createSocket());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    // 新增句子信息类
    private static class SentenceInfo {
        String text;
        long bg;
        long ed;
        int wordCount;

        public SentenceInfo(String text, long bg, long ed, int wordCount) {
            this.text = text;
            this.bg = bg;
            this.ed = ed;
            this.wordCount = wordCount;
        }
    }

    /**
     * 解析转写结果并构建增强版文本（包含停顿时间和语速分析）
     *
     * @param message 转写服务返回的原始消息字符串
     * @return 增强后的文本结果，格式如："句子内容(停顿X秒，语速快/中等/慢）"
     */
    public static String getContent(String message, WebSocketSession frontSession) {
        String sessionId = frontSession.getId();
        List<SentenceInfo> sentences = sentenceStore.computeIfAbsent(sessionId, k -> new ArrayList<>());

        try {
            // 将 JSON 字符串解析为 JSONObject
            JSONObject messageObj = JSON.parseObject(message);
            // 获取中文转写内容
            JSONObject cn = messageObj.getJSONObject("cn");
            // 获取转写状态对象
            JSONObject st = cn.getJSONObject("st");

            if (!"0".equals(st.getString("type"))) {
                return "doing";
            }
            System.out.println("处理的message:"+message);
            // 获取实时转写结果数组
            JSONArray rtArr = st.getJSONArray("rt");
            // 获取当前段落的开始时间（单位：毫秒）
            long bg = Long.parseLong(st.getString("bg"));
            // 获取当前段落的结束时间（单位：毫秒）
            long ed = Long.parseLong(st.getString("ed"));

            // 构建最终文本内容
            StringBuffer resultBuilder = new StringBuffer();
            // 统计非标点词数量，用于语速计算
            int wordCount = 0;

            // 遍历每个词片段
            for (int i = 0; i < rtArr.size(); i++) {
                JSONObject rtArrObj = rtArr.getJSONObject(i);
                JSONArray wsArr = rtArrObj.getJSONArray("ws");

                for (int j = 0; j < wsArr.size(); j++) {
                    JSONObject wsArrObj = wsArr.getJSONObject(j);
                    JSONArray cwArr = wsArrObj.getJSONArray("cw");

                    for (int k = 0; k < cwArr.size(); k++) {
                        JSONObject cwArrObj = cwArr.getJSONObject(k);
                        String wStr = cwArrObj.getString("w"); // 词语识别结果
                        String wp = cwArrObj.getString("wp"); // 词标识（n-普通词；s-顺滑词；p-标点）

                        // 只统计非标点词
                        if (!"p".equals(wp)) {
                            wordCount++;
                        }
                        resultBuilder.append(wStr); // 拼接完整句子
                    }
                }
            }

            // 将当前段落信息保存到 SentenceInfo 列表中
            sentences.add(new SentenceInfo(
                    resultBuilder.toString(), // 完整句子
                    bg,                       // 开始时间
                    ed,                       // 结束时间
                    wordCount                 // 非标点词数量
            ));

            // 更新存储
            sentenceStore.put(sessionId, sentences);

        } catch (Exception e) {
            // 如果解析失败，直接返回原始消息
            return message;
        }

        // 构建增强版结果（包含停顿和语速分析）
        return buildEnhancedResult(sentences);
    }

    /**
     * 构建增强版结果，包括：
     * - 相邻句子之间的停顿时间
     * - 当前句子的语速分析（字数/时长）
     *
     * @param sentences 解析出的句子列表
     * @return 带语义增强的结果字符串
     */
    private static String buildEnhancedResult(List<SentenceInfo> sentences) {
        StringBuilder finalResult = new StringBuilder();
        long prevEd = 0; // 上一句的结束时间

        for (SentenceInfo sentence : sentences) {
            // 打印每个 SentenceInfo 的详细信息
            System.out.println("SentenceInfo: text=" + sentence.text +
                    ", bg=" + sentence.bg +
                    ", ed=" + sentence.ed +
                    ", wordCount=" + sentence.wordCount);

            // 计算与上一句之间的停顿时间（单位：ms）
            long pauseTime = prevEd > 0 ? sentence.ed - prevEd : 0;

            // 计算语速（字/秒）
            double durationSec = (sentence.ed - sentence.bg) / 1000.0;
            String speedLevel = "快"; // 默认是“快”
            double speed = 0;

            if (durationSec > 0) {
                speed = sentence.wordCount / durationSec;
                if (speed < 3) {
                    speedLevel = "慢";
                } else if (speed < 5) {
                    speedLevel = "中等";
                }
            }
            //句子停顿计算
            if (pauseTime > 0) {
                finalResult.append(String.format("(停顿%d秒)", pauseTime / 1000));
            }
            // 拼接句子 + 停顿时长 + 语速分析（含具体数值）
            finalResult.append(sentence.text);
            // 添加语速级别和具体数值，保留一位小数
            finalResult.append(String.format("(语速%s，%.1f字/秒）", speedLevel, speed));

            prevEd = sentence.ed; // 更新上一句结束时间
        }

        return finalResult.toString();
    }
}